package top.lhj.security.example.config;

import com.alibaba.fastjson2.JSONObject;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

import static org.springframework.security.config.Customizer.withDefaults;

/**
 * @Author LiHaoJie
 * @Create 2024/2/2 21:18
 * @Version 1.0
 * 注意：开启SpringSecurity注解,在SpringBoot项目中此注解可以省略因为SpringBoot
 * 在启动时会判断是否加了依赖如果发现这个类存在会添加EnableWebSecurity
 * 如果我们使用了自定义配置了用户名和密码，那么在配置文件里的spring.security.user.name=xxx将会失效
 */
@Component
//@EnableWebSecurity
@EnableMethodSecurity
public class WebSecurityConfig {
    
    /**
     * @Param 过滤器
     * authorizeRequests(): 开启授权保护
     * anyRequest()：对所有请求开启授权保护
     * authenticated()：已认证请求会自动被授权
     * formLogin(withDefaults()): 表单授权方式
     * httpBasic(withDefaults()): 基本授权方式
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests(authorize -> authorize
//                .requestMatchers("/user/add").hasAuthority("USER_ADD")
//                .requestMatchers("/user/list").hasAuthority("USER_LIST")
                .requestMatchers("/user/**").hasRole("ADMIN")
                .anyRequest()
                .authenticated()
        );
        
        //登录处理
        http.formLogin(form -> {
            form.loginPage("/login").permitAll();
//          form.usernameParameter("myusername"); //设置表单中提交的name
//          form.passwordParameter("mypassword"); //设置前端表单提交的name
            form.successHandler(new MyAuthenticationSuccessHandler());
            form.failureHandler(new MyAuthenticationFailureHandler());
        });
//                .formLogin(withDefaults());
//                .httpBasic(withDefaults());
        
        //关闭csrf攻击
        http.csrf(csrf -> csrf.disable());
        
        //注销处理
        http.logout(logout -> {
            logout.logoutSuccessHandler(new MyLogoutSuccessHandler());
        });
        
        //未认证处理
        http.exceptionHandling(exception -> {
            exception.authenticationEntryPoint(new MyAuthenticationEntryPoint());
            //写法一：Lambda表达式
            /*exception.accessDeniedHandler((request, response, accessDeniedException) -> {
                Map<String, Object> map = new HashMap<>();
                map.put("code", "403");
                map.put("message", "Forbidden");
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().println(JSONObject.toJSONString(map));
            });*/
            //写法二：通过继承AccessDeniedHandler
            exception.accessDeniedHandler(new MyAccessDeniedHandler());
        });
        
        //处理用户多地登录
        http.sessionManagement(session -> {
            session.maximumSessions(1).expiredSessionStrategy(new MySessionInformationExpiredStrategy());
        });
        
        //处理跨域
        http.cors(withDefaults());
        
        
        
        return http.build();
    }
    
    /*@Bean
    public UserDetailsService userDetailsService() {
        //
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(
                User.withDefaultPasswordEncoder()
                .username("user")
                .password("password")
                .roles("USER")
                .build()
        );
        return manager;
    }*/
    
    /*@Bean
    public UserDetailsService userDetailsService() {
        DbUserDetailsManager manager = new DbUserDetailsManager();
        return manager;
    }*/
    
}
